package com.hfjyz.expert.expertcall.service;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.transaction.annotation.Transactional;

import com.hfjyz.base.bean.SearchCondition;
import com.hfjyz.base.constant.BaseConstant;
import com.hfjyz.base.entity.CallEntity;
import com.hfjyz.base.entity.ExpertEntity;
import com.hfjyz.base.exception.BaseException;
import com.hfjyz.base.util.ExcelUtil;
import com.hfjyz.expert.expert.bean.ExpertBean;
import com.hfjyz.expert.expert.dao.ExpertDao;
import com.hfjyz.expert.expertcall.bean.ExpertCallBean;
import com.hfjyz.expert.expertcall.bean.ExpertCallExcelBean;
import com.hfjyz.expert.expertcall.bean.ExpertCallSearchBean;
import com.hfjyz.expert.expertcall.dao.ExpertCallDao;
import com.hfjyz.expert.expertcall.entity.ExpertCallEntity;

public class ExpertCallService {
    private static final Log SYS_LOG = LogFactory.getLog(BaseConstant.SYS_LOG);

    private ExpertCallDao dao = null;
    
    private ExpertDao expertDao = null;

    public ExpertCallDao getDao() {
        return dao;
    }

    public void setDao(ExpertCallDao dao) {
        this.dao = dao;
    }

    public ExpertDao getExpertDao() {
        return expertDao;
    }

    public void setExpertDao(ExpertDao expertDao) {
        this.expertDao = expertDao;
    }

    public List<ExpertCallBean> findExpertCall(SearchCondition cond,
            ExpertCallSearchBean expertCallSearch) throws BaseException {
        try {
            List<ExpertCallEntity> entityList = null;
            if (expertCallSearch != null) {
                entityList = dao.findCall(cond, expertCallSearch.getWhereClause("call", "expert"),
                        expertCallSearch.getParamList());
            } else {
                entityList = dao.findCall(cond, null, null);
            }

            List<ExpertCallBean> beanList = new ArrayList<ExpertCallBean>();
            for (ExpertCallEntity entity : entityList) {
                ExpertCallBean bean = new ExpertCallBean(entity);
                beanList.add(bean);
            }

            SYS_LOG.info("专家调用信息取得成功。");
            return beanList;
        } catch (Exception e) {
            SYS_LOG.error("专家调用信息取得失败！", e);
            throw new BaseException("专家调用信息取得失败！", e);
        }
    }

    public long getExpertCallCount(ExpertCallSearchBean expertCallSearch) throws BaseException {
        try {
            long count = 0L;
            if (expertCallSearch != null) {
                count = dao.countCall(" ExpertEntity expert ", "expert", 
                        expertCallSearch.getWhereClause("call", "expert"),
                        expertCallSearch.getParamList());
            } else {
                count = dao.countCall(" ExpertEntity expert ", "expert",null, null);
            }
            SYS_LOG.info("专家调用信息总数取得成功。 总数=" + count);

            return count;
        } catch (Exception e) {
            SYS_LOG.error("专家调用信息总数取得失败！", e);
            throw new BaseException("专家调用信息总数取得失败！", e);
        }
    }

    @Transactional
    public void saveExpertCall(List<ExpertCallBean> beanList) throws BaseException {
        for (ExpertCallBean bean : beanList) {
            saveExpertCall(bean);
        }
    }

    @Transactional
    public void saveExpertCall(ExpertCallBean bean) throws BaseException {
        try {
            String msg = bean.validate();
            if (msg != null && !msg.isEmpty()) {
                throw new BaseException(msg);
            }
            CallEntity entity = null;
            boolean isAdd = false;
            if (bean.getId() != null) {
                entity = dao.get(bean.getId());
            } else {
                long count = dao.countCallByTargetAndName(bean.getCallName(), 
                        bean.getTarget().getId());
                if (count > 0) {
                    throw new BaseException("指定的专家调用信息已经存在，请确认！");
                }
                entity = new CallEntity();
                isAdd = true;
            }
            mergeEntity(bean, entity);

            dao.saveOrUpdate(entity);
            if (isAdd) {
                // 更新调用次数
                ExpertEntity expert = expertDao.get(bean.getTarget().getId());
                expert.setCallTimes(expert.getCallTimes() + 1);
                expertDao.saveOrUpdate(expert);
            }

            SYS_LOG.info("专家调用信息保存成功。 expertCall=" + bean.toString());
        } catch (BaseException e) {
            SYS_LOG.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            SYS_LOG.error("专家调用信息保存失败！", e);
            throw new BaseException("专家调用信息保存失败！", e);
        }
    }

    private void mergeEntity(ExpertCallBean bean, CallEntity e) {
        e.setCallName(bean.getCallName());
        e.setCallReason(bean.getCallReason());
        e.setCallRemark(bean.getCallRemark());
        e.setCallType(dao.getType());
        e.setId(bean.getId());
        e.setTargetId(bean.getTarget().getId());
        e.setCallAim(bean.getCallAim());
    }

    @Transactional
    public void deleteExpertCall(List<Integer> idList) throws BaseException {
        try {
            for (Integer id : idList) {
                CallEntity entity = dao.get(id);
                ExpertEntity expert = expertDao.get(entity.getTargetId());
                expert.setCallTimes(expert.getCallTimes() - 1);

                dao.delete(id);
                expertDao.saveOrUpdate(expert);
            }
            SYS_LOG.info("专家调用删除成功。 idList=" + idList.toString());
        } catch (Exception e) {
            SYS_LOG.error("专家调用删除失败！", e);
            throw new BaseException("专家调用删除失败！", e);
        }
    }

    public ExpertCallBean updateInitExpertCall(Integer id) throws BaseException {
        try {
            CallEntity call = dao.get(id);
            ExpertEntity expert = dao.findTargetById(call.getTargetId());
            ExpertCallBean bean = new ExpertCallBean(call, expert);

            SYS_LOG.info("取得专家信息成功。 bean=" + bean);

            return bean;
        } catch (Exception e) {
            SYS_LOG.error("取得专家信息失败！", e);
            throw new BaseException("取得专家信息失败！", e);
        }
    }

    public Workbook exportExpertCall(String templatePath, List<ExpertCallExcelBean> expertCallList)
            throws BaseException {
        InputStream inputXLStream = null;
        try {
            inputXLStream = new BufferedInputStream(new FileInputStream(templatePath));
            ExcelUtil<ExpertCallExcelBean> util = new ExcelUtil<ExpertCallExcelBean>();
            
            return util.writeToExcel(inputXLStream, expertCallList, BaseConstant.EXCEL_EXPERT_BEAN_LIST);
        } catch (Exception e) {
            throw new BaseException("导出Excel失败！");
        }
    }

    public List<ExpertBean> findAllExpert() throws BaseException {
        try {
            List<ExpertEntity> entityList = expertDao.findAll();

            List<ExpertBean> beanList = new ArrayList<ExpertBean>();
            for (ExpertEntity entity : entityList) {
                ExpertBean bean = new ExpertBean(entity);
                beanList.add(bean);
            }

            SYS_LOG.info("取得所有专家信息成功。");
            return beanList;
        } catch (Exception e) {
            SYS_LOG.error("取得所有专家信息失败。", e);
            throw new BaseException("取得所有专家信息失败。", e);
        }
    }
}
